home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / Capclip.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  9.0 KB  |  316 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19. #include <crtdbg.h>
  20. #include <windows.h>
  21. #include <vfw.h>
  22.  
  23. #include "resource.h"
  24. #include "oshelper.h"
  25. #include "vbitmap.h"
  26. #include "helpfile.h"
  27. #include "Error.h"
  28. #include "ClippingControl.h"
  29.  
  30. #include "capclip.h"
  31.  
  32. extern HINSTANCE g_hInst;
  33. extern RECT g_rCaptureClip;
  34.  
  35. extern LRESULT CALLBACK CaptureStatusCallback(HWND hWnd, int nID, LPCSTR lpsz);
  36.  
  37. CaptureFrameSource::CaptureFrameSource(HWND hwndCapture)
  38.     :bmihSrc(NULL)
  39.     ,hic(NULL)
  40.     ,fDecompressionOk(false)
  41.     ,pFrameBuffer(NULL)
  42.     {
  43.  
  44.     try {
  45.         int fsize;
  46.  
  47.         // determine native video format of capture device
  48.  
  49.         if ((fsize = capGetVideoFormatSize(hwndCapture))<=0)
  50.             throw MyError("Couldn't get video format.");
  51.  
  52.         if (!(bmihSrc = (BITMAPINFOHEADER *)allocmem(fsize)))
  53.             throw MyMemoryError();
  54.  
  55.         if (!capGetVideoFormat(hwndCapture, bmihSrc, fsize))
  56.             throw MyError("Couldn't get video format.");
  57.  
  58.         // Construct a format for uncompressed RGB, if we don't already have one.
  59.  
  60.         if (bmihSrc->biCompression != BI_RGB) {
  61.  
  62.             // Attempt RGB24 first.
  63.  
  64.             memcpy(&bmihDecomp, bmihSrc, sizeof(BITMAPINFOHEADER));
  65.             bmihDecomp.biSize            = sizeof(BITMAPINFOHEADER);
  66.             bmihDecomp.biPlanes            = 1;
  67.             bmihDecomp.biBitCount        = 24;
  68.             bmihDecomp.biCompression    = BI_RGB;
  69.             bmihDecomp.biSizeImage        = ((bmihDecomp.biWidth*3+3)&-4) * bmihDecomp.biHeight;
  70.  
  71.             // Attempt to find a decompressor.
  72.  
  73. //            hic = ICOpen('CDIV', bmihSrc->biCompression, ICMODE_DECOMPRESS);
  74.  
  75.             hic = ICLocate(ICTYPE_VIDEO, bmihSrc->biCompression, bmihSrc, NULL, ICMODE_DECOMPRESS);
  76.  
  77.             if (!hic)
  78.                 hic = ICLocate(ICTYPE_VIDEO, NULL, bmihSrc, NULL, ICMODE_DECOMPRESS);
  79.  
  80.             if (!hic)
  81.                 throw MyError("No decompressor is available for the current capture format.");
  82.  
  83.             // Try some formats.  24-bit first, then 32-bit.
  84.  
  85.             do {
  86.  
  87.                 // See if RGB24 works.
  88.  
  89.                 if (ICERR_OK == ICDecompressBegin(hic, bmihSrc, &bmihDecomp))
  90.                     break;
  91.  
  92.                 // Nope, try RGB32.
  93.  
  94.                 bmihDecomp.biBitCount        = 32;
  95.                 bmihDecomp.biCompression    = BI_RGB;
  96.                 bmihDecomp.biSizeImage        = bmihDecomp.biWidth*4 * bmihDecomp.biHeight;
  97.  
  98.                 if (ICERR_OK == ICDecompressBegin(hic, bmihSrc, &bmihDecomp))
  99.                     break;
  100.  
  101.                 // Ick, try RGB15.
  102.  
  103.                 bmihDecomp.biBitCount        = 16;
  104.                 bmihDecomp.biCompression    = BI_RGB;
  105.                 bmihDecomp.biSizeImage        = ((bmihDecomp.biWidth+1)&-2)*2 * bmihDecomp.biHeight;
  106.  
  107.                 if (ICERR_OK == ICDecompressBegin(hic, bmihSrc, &bmihDecomp))
  108.                     break;
  109.  
  110.                 // Nope, we're screwed.
  111.  
  112.                 throw MyError("Cannot find a way to decompress capture data to RGB format.");
  113.  
  114.             } while(false);
  115.  
  116.             // Okay, decompressor is ready to go.  Cool.
  117.  
  118.             fDecompressionOk = true;
  119.  
  120.             // Now that we have the format, we need this 'framebuffer' thing.
  121.  
  122.             pFrameBuffer = VirtualAlloc(NULL, bmihDecomp.biSizeImage + (bmihDecomp.biBitCount==24 ? 1 : 0), MEM_COMMIT, PAGE_READWRITE);
  123.  
  124.             if (!pFrameBuffer)
  125.                 throw MyMemoryError();
  126.  
  127.             // Create a suitable VBitmap for the framebuffer.
  128.  
  129.             vbAnalyze = VBitmap(pFrameBuffer, &bmihDecomp);
  130.  
  131.         } else {    // uncompressed RGB already
  132.  
  133.             // Create a suitable VBitmap for the incoming stream.
  134.  
  135.             vbAnalyze = VBitmap(NULL, bmihSrc);
  136.  
  137.         }
  138.  
  139.     } catch(MyError) {
  140.         _destruct();
  141.         throw;
  142.     }
  143. }
  144.  
  145. void CaptureFrameSource::_destruct() {
  146.     if (bmihSrc)            { freemem(bmihSrc); bmihSrc = NULL; }
  147.     if (fDecompressionOk)    { ICDecompressEnd(hic); fDecompressionOk = false; }
  148.     if (hic)                { ICClose(hic); hic = NULL; }
  149.     if (pFrameBuffer)        { VirtualFree(pFrameBuffer, 0, MEM_RELEASE); pFrameBuffer = NULL; }
  150. }
  151.  
  152. CaptureFrameSource::~CaptureFrameSource() {
  153.     _destruct();
  154. }
  155.  
  156. bool CaptureFrameSource::CheckFrameSize(int w, int h) {
  157.     return w == bmihSrc->biWidth && bmihSrc->biHeight;
  158. }
  159.  
  160. const VBitmap *CaptureFrameSource::Decompress(VIDEOHDR *pvhdr) {
  161.     if (hic) {
  162.         DWORD err;
  163.  
  164.         err = ICDecompress(
  165.                 hic,
  166.                 pvhdr->dwFlags & VHDR_KEYFRAME ? AVIIF_KEYFRAME : 0,
  167.                 bmihSrc,
  168.                 pvhdr->lpData,
  169.                 &bmihDecomp,
  170.                 pFrameBuffer);
  171.  
  172.         if (err != ICERR_OK)
  173.             throw MyICError("Histogram", err);
  174.     } else
  175.         vbAnalyze.data = (Pixel *)pvhdr->lpData;
  176.  
  177.     return &vbAnalyze;
  178. }
  179.  
  180. ///////////////////////////////////////////////////////////////////////////
  181.  
  182. static CaptureFrameSource *g_pClippingDecoder;
  183. static HWND g_hwndClippingDisplay;
  184.  
  185. LRESULT CALLBACK CaptureClippingFrameProc(HWND hWnd, VIDEOHDR *vhdr) {
  186.     BITMAPINFOHEADER bih;
  187.  
  188.     try {
  189.         const VBitmap *vbm = g_pClippingDecoder->Decompress(vhdr);
  190.  
  191.         vbm->MakeBitmapHeader(&bih);
  192.  
  193.         SendMessage(g_hwndClippingDisplay, CCM_BLITFRAME, (WPARAM)&bih, (LPARAM)vbm->data);
  194.     } catch(MyError e) {
  195.     }
  196.  
  197.     return 0;
  198. }
  199.  
  200. BOOL APIENTRY CaptureClippingDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  201.     HWND hwndCapture = (HWND)GetWindowLong(hDlg, DWL_USER);
  202.  
  203.     switch (message)
  204.     {
  205.         case WM_INITDIALOG:
  206.             {
  207.                 CAPSTATUS cs;
  208.                 ClippingControlBounds ccb;
  209.                 LONG hborder, hspace;
  210.                 RECT rw, rc, rcok, rccancel;
  211.                 HWND hWnd, hWndCancel;
  212.                 hwndCapture = (HWND)lParam;
  213.  
  214.                 SetWindowLong(hDlg, DWL_USER, lParam);
  215.  
  216.                 g_hwndClippingDisplay = hWnd = GetDlgItem(hDlg, IDC_BORDERS);
  217.                 ccb.x1    = g_rCaptureClip.left;
  218.                 ccb.x2    = g_rCaptureClip.right;
  219.                 ccb.y1    = g_rCaptureClip.top;
  220.                 ccb.y2    = g_rCaptureClip.bottom;
  221.  
  222.                 capGetStatus(hwndCapture, &cs, sizeof cs);
  223.                 SendMessage(hWnd, CCM_SETBITMAPSIZE, 0, MAKELONG(cs.uiImageWidth,cs.uiImageHeight));
  224.                 SendMessage(hWnd, CCM_SETCLIPBOUNDS, 0, (LPARAM)&ccb);
  225.  
  226.                 GetWindowRect(hDlg, &rw);
  227.                 GetWindowRect(hWnd, &rc);
  228.                 hborder = rc.left - rw.left;
  229.                 ScreenToClient(hDlg, (LPPOINT)&rc.left);
  230.                 ScreenToClient(hDlg, (LPPOINT)&rc.right);
  231.  
  232.                 SetWindowPos(hDlg, NULL, 0, 0, (rc.right - rc.left) + hborder*2, (rw.bottom-rw.top)+(rc.bottom-rc.top), SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOMOVE);
  233.  
  234.                 hWndCancel = GetDlgItem(hDlg, IDCANCEL);
  235.                 hWnd = GetDlgItem(hDlg, IDOK);
  236.                 GetWindowRect(hWnd, &rcok);
  237.                 GetWindowRect(hWndCancel, &rccancel);
  238.                 hspace = rccancel.left - rcok.right;
  239.                 ScreenToClient(hDlg, (LPPOINT)&rcok.left);
  240.                 ScreenToClient(hDlg, (LPPOINT)&rcok.right);
  241.                 ScreenToClient(hDlg, (LPPOINT)&rccancel.left);
  242.                 ScreenToClient(hDlg, (LPPOINT)&rccancel.right);
  243.                 SetWindowPos(hWndCancel, NULL, rc.right - (rccancel.right-rccancel.left), rccancel.top + (rc.bottom-rc.top), 0,0,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE);
  244.                 SetWindowPos(hWnd, NULL, rc.right - (rccancel.right-rccancel.left) - (rcok.right-rcok.left) - hspace, rcok.top + (rc.bottom-rc.top), 0,0,SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOSIZE);
  245.  
  246.                 SetTimer(hDlg, 1, 500, NULL);
  247.  
  248.                 if (g_pClippingDecoder)
  249.                     capSetCallbackOnFrame(hwndCapture, CaptureClippingFrameProc);
  250.             }
  251.  
  252.             return (TRUE);
  253.  
  254.         case WM_COMMAND:
  255.             switch(LOWORD(wParam)) {
  256.             case IDOK:
  257.                 {
  258.                     ClippingControlBounds ccb;
  259.  
  260.                     SendMessage(GetDlgItem(hDlg, IDC_BORDERS), CCM_GETCLIPBOUNDS, 0, (LPARAM)&ccb);
  261.                     g_rCaptureClip.left = ccb.x1;
  262.                     g_rCaptureClip.top = ccb.y1;
  263.                     g_rCaptureClip.right = ccb.x2;
  264.                     g_rCaptureClip.bottom = ccb.y2;
  265.                     capSetCallbackOnFrame(hwndCapture, NULL);
  266.                     EndDialog(hDlg, TRUE);
  267.                 }
  268.                 return TRUE;
  269.             case IDCANCEL:
  270.                 capSetCallbackOnFrame(hwndCapture, NULL);
  271.                 EndDialog(hDlg, FALSE);
  272.                 return TRUE;
  273.             case IDC_BORDERS:
  274. //                guiPositionBlit((HWND)lParam, guiPositionHandleCommand(wParam, lParam));
  275.                 return TRUE;
  276.             }
  277.             break;
  278.  
  279.         case WM_TIMER:
  280.             capGrabFrameNoStop(hwndCapture);
  281.             break;
  282.  
  283.         case WM_NOTIFY:
  284.             {
  285.                 const VBitmap *vbm = g_pClippingDecoder->getFrameBuffer();
  286.                 BITMAPINFOHEADER bih;
  287.  
  288.                 vbm->MakeBitmapHeader(&bih);
  289.  
  290.                 SendMessage(g_hwndClippingDisplay, CCM_BLITFRAME, (WPARAM)&bih, (LPARAM)vbm->data);
  291.             }
  292.             break;
  293.  
  294.     }
  295.     return FALSE;
  296. }
  297.  
  298. void CaptureShowClippingDialog(HWND hwndCapture) {
  299.     g_pClippingDecoder = new CaptureFrameSource(hwndCapture);
  300.     CAPSTATUS cs;
  301.  
  302.     capGetStatus(hwndCapture, &cs, sizeof cs);
  303.     capOverlay(hwndCapture, FALSE);
  304.     capPreview(hwndCapture, FALSE);
  305.  
  306.     DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_CAPTURE_CLIPPING), GetParent(hwndCapture), CaptureClippingDlgProc, (LPARAM)hwndCapture);
  307.  
  308.     if (cs.fOverlayWindow)
  309.         capOverlay(hwndCapture, TRUE);
  310.  
  311.     if (cs.fLiveWindow)
  312.         capPreview(hwndCapture, TRUE);
  313.  
  314.     delete g_pClippingDecoder;
  315. }
  316.